/*
 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
 * Licensed under the MIT License, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Subscription } from './Subscription';
import { BusRuntime } from '../bus/BusRuntime';
import { MethodParameters } from '../entry/MethodParameters';
import { SubscriptionContext } from './SubscriptionContext';
import type { IMessageDispatcher } from '../dispatch/IMessageDispatcher';
import { FilteredMessageDispatcher } from '../dispatch/FilteredMessageDispatcher';
import { MessageDispatcher } from '../dispatch/MessageDispatcher';
import type { IHandlerInvocation } from '../dispatch/IHandlerInvocation';
import { AsynchronousHandlerInvocation } from '../dispatch/AsynchronousHandlerInvocation';
import { SynchronizedHandlerInvocation } from '../dispatch/SynchronizedHandlerInvocation';

export class SubscriptionFactory {
    createSubscription(runtime: BusRuntime, parameters: MethodParameters, isStrong: boolean): Subscription {
        let context = new SubscriptionContext(runtime, parameters);
        let invocation = this.buildInvocationForHandler(context);
        let dispatch = this.buildDispatcher(context, invocation);
        return new Subscription(context, dispatch, isStrong);
    }

    buildDispatcher(context: SubscriptionContext, invocation: IHandlerInvocation): IMessageDispatcher {
        let dispatcher: IMessageDispatcher;
        let isFiltered = context.getHandleParameters().isFiltered();
        if (isFiltered) {
            dispatcher = new FilteredMessageDispatcher(context, invocation);
        }
        if (!dispatcher) {
            dispatcher = new MessageDispatcher(context, invocation);
        }
        return dispatcher;
    }

    buildInvocationForHandler(context: SubscriptionContext): IHandlerInvocation {
        let invocation: IHandlerInvocation;
        if (context.getHandleParameters().isAsynchronous()) {
            invocation = new AsynchronousHandlerInvocation();
        } else {
            invocation = new SynchronizedHandlerInvocation();
        }
        return invocation;
    }
}